﻿
using DifyToOpenAI.Common;
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;


namespace DifyToOpenAI.Models
{
    /// <summary>
    /// 表示流式聊天补全响应中的一个数据块。
    /// Represents a chunk in a streaming chat completion response.
    /// </summary>
    public class ChatCompletionChunk
    {
        public ChatCompletionChunk() { }

        public ChatCompletionChunk(string content,string id="", string role= "assistant") 
        {
            if (string.IsNullOrWhiteSpace(id))
            {
               // this.id = Guid.NewGuid().ToString();
            }
            else { this.id = id; }
           
            this.choices=new List<ChoiceChunk>();
            ChoiceChunk choiceChunk = new ChoiceChunk();
            choiceChunk.delta = new Delta(role, content);
            this.choices.Add(choiceChunk);
        }
        /// <summary>
        /// 数据块的唯一标识符。
        /// A unique identifier for the chunk.
        /// </summary>
        public string? id { get; set; }= Guid.NewGuid().ToString();

        /// <summary>
        /// 对象类型，通常是 "chat.completion.chunk"。
        /// The object type, which is typically "chat.completion.chunk".
        /// </summary>
        [JsonPropertyName("object")]
        public string? @object { get; set; } = "chat.completion.chunk";

        /// <summary>
        /// 数据块创建时的 Unix 时间戳。
        /// The Unix timestamp (in seconds) of when the chunk was created.
        /// </summary>
        public long? created { get; set; } = ComServices.TimestampSeconds();

        /// <summary>
        /// 所使用的模型。
        /// The model used for the completion.
        /// </summary>
        public string? model { get; set; }

        /// <summary>
        /// 系统的指纹信息，可用于跟踪模型版本。
        /// The system fingerprint, which can be used to track model versions.
        /// </summary>
        public string? system_fingerprint { get; set; }

        /// <summary>
        /// 补全选择的列表。在流式传输中通常只包含一个元素。
        /// A list of completion choices. Usually contains one element in streaming mode.
        /// </summary>
        public List<ChoiceChunk>? choices { get; set; } = new List<ChoiceChunk>();

        [JsonIgnore]
        private string realJsonstring = string.Empty;

        /// <summary>
        /// 获取或设置请求的真实 JSON 字符串表示。设置此属性将触发反序列化。
        /// Gets or sets the real JSON string representation of the request. Setting this property will trigger deserialization.
        /// </summary>
        [JsonIgnore]
        public string? RealJsonstring
        {
            get { return realJsonstring; }
            set
            {
                realJsonstring = value!;
                try
                {
                    DeserializeChatCompletionChunk(value!);
                }
                catch (Exception)
                {
                    // 可以选择记录异常或按需处理
                    // Optionally log the exception or handle it as needed
                }
            }
        }

        /// <summary>
        /// 将 JSON 字符串反序列化到当前的 ChatCompletionChunk 实例中。
        /// 此方法逐个解析 JSON 属性，即使某些属性解析失败，也会继续尝试解析其他属性。
        /// Deserializes a JSON string into the current ChatCompletionChunk instance.
        /// This method parses JSON properties one by one, continuing even if some fail.
        /// </summary>
        /// <param name="json">需要解析的 JSON 字符串。The JSON string to be parsed.</param>
        public virtual void DeserializeChatCompletionChunk(string json)
        {
            if (string.IsNullOrEmpty(json)) return;

            var jsonNode = JsonNode.Parse(json);
            if (jsonNode == null) return;

            // --- 解析顶层属性 ---
            try { if (jsonNode["id"] != null) this.id = jsonNode["id"]!.GetValue<string>(); } catch { }
            try { if (jsonNode["object"] != null) this.@object = jsonNode["object"]!.GetValue<string>(); } catch { }
            try { if (jsonNode["created"] != null) this.created = jsonNode["created"]!.GetValue<long>(); } catch { }
            try { if (jsonNode["model"] != null) this.model = jsonNode["model"]!.GetValue<string>(); } catch { }
            try { if (jsonNode["system_fingerprint"] != null) this.system_fingerprint = jsonNode["system_fingerprint"]!.GetValue<string>(); } catch { }

            // --- 解析 choices 数组 ---
            try
            {
                var choicesNode = jsonNode["choices"]?.AsArray();
                if (choicesNode != null)
                {
                    this.choices = new List<ChoiceChunk>();
                    foreach (var choiceNode in choicesNode)
                    {
                        if (choiceNode == null) continue;

                        var choiceChunk = new ChoiceChunk();

                        try { if (choiceNode["index"] != null) choiceChunk.index = choiceNode["index"]!.GetValue<int>(); } catch { }
                        try { if (choiceNode["finish_reason"] != null) choiceChunk.finish_reason = choiceNode["finish_reason"]!.GetValue<string>(); } catch { }
                        try { if (choiceNode["logprobs"] != null) choiceChunk.logprobs = choiceNode["logprobs"]!.ToJsonString(); } catch { }

                        // --- 解析 delta 对象 ---
                        try
                        {
                            var deltaNode = choiceNode["delta"];
                            if (deltaNode != null)
                            {
                                choiceChunk.delta = new Delta();
                                try { if (deltaNode["role"] != null) choiceChunk.delta.role = deltaNode["role"]!.GetValue<string>(); } catch { }
                                try { if (deltaNode["content"] != null) choiceChunk.delta.content = deltaNode["content"]!.GetValue<string>(); } catch { }
                            }
                        }
                        catch { }

                        this.choices.Add(choiceChunk);
                    }
                }
            }
            catch { }
        }
    }

    /// <summary>
    /// 表示聊天补全数据块中的一个选择。
    /// Represents a choice within a chat completion chunk.
    /// </summary>
    public class ChoiceChunk
    {
        public ChoiceChunk() { }
        /// <summary>
        /// 选择的索引。
        /// The index of the choice.
        /// </summary>
        public int? index { get; set; } = 0;

        /// <summary>
        /// 包含增量更新内容的对象。
        /// An object containing the incremental update content.
        /// </summary>
        public Delta? delta { get; set; }

        /// <summary>
        /// 日志概率信息。
        /// Log probability information.
        /// </summary>
        public object? logprobs { get; set; }

        /// <summary>
        /// 补全停止的原因，例如 "stop" 或 "length"。
        /// The reason the model stopped generating tokens, e.g., "stop" or "length".
        /// </summary>
        public string? finish_reason { get; set; }
    }

    /// <summary>
    /// 表示消息的增量变化。
    /// Represents an incremental change to a message.
    /// </summary>
    public class Delta
    {
        public Delta() { }

        public Delta(string role, string content)
        { 
            this.role = role;
            this.content = content;
        }
        /// <summary>
        /// 消息作者的角色。通常只在第一个数据块中出现。
        /// The role of the message author. Usually appears only in the first chunk.
        /// </summary>
        public string? role { get; set; } = "assistant";

        /// <summary>
        /// 增量内容。
        /// The incremental content.
        /// </summary>
        public string? content { get; set; }
    }
}
